<template>
    <div ref="chartRef" class="pie-chart" />
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, toValue } from "vue";
import type { MaybeRef } from "@vueuse/shared";
import * as echarts from "echarts/core";
import { PieChart } from "echarts/charts";
import { TooltipComponent, LegendComponent, TitleComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

// ECharts 按需注册
echarts.use([PieChart, TooltipComponent, LegendComponent, TitleComponent, CanvasRenderer]);

export interface PieData {
    name: string;
    value: number;
}

export interface PieConfig {
    title?: string;
    radius?: (string | number)[];
    roseType?: boolean | "radius" | "area";
    colors?: string[];
    showLabel?: boolean;
    centerText?: boolean;
}

interface Props {
    data: MaybeRef<PieData[]>;
    config?: MaybeRef<PieConfig>;
    height?: string;
}

const props = withDefaults(defineProps<Props>(), {
    config: () => ({}),
});

const chartRef = ref<HTMLDivElement>();
let chart: echarts.ECharts | null = null;

// 合并默认配置
const opt = computedPieOption();

// 生成 option
function computedPieOption() {
    const cfg = toValue(props.config) || {};
    const { showLabel = false } = cfg;
    const colors = ["#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", "#3ba272", "#fc8452"];
    return {
        tooltip: { trigger: "item" },
        legend: { show: true, right: "2%", bottom: "2%", align: "right", orient: "vertical", textStyle: { color: "#fff" } },
        grid: { top: 5, bottom: 5, left: 5, right: 5 },
        color: colors,
        series: [
            {
                name: "",
                type: "pie",
                radius: ["55%", "70%"],
                avoidLabelOverlap: false,
                padAngle: 5,
                itemStyle: { borderRadius: 10 },
                label: { show: showLabel, position: "center" },
                emphasis: { label: { show: true, fontSize: 24, fontWeight: "bold" } },
                labelLine: { show: false },
                data: toValue(props.data)
            },
        ],
    };
}

function initChart() {
    if (!chartRef.value) return;
    chart = echarts.init(chartRef.value);
    chart.setOption(opt);
}

function resize() {
    chart?.resize();
}

// 监听数据变化
watch(
    () => [props.data, props.config],
    () => {
        chart?.setOption(opt);
    },
    { deep: true }
);

// 监听容器大小
const ro = new ResizeObserver(() => resize());
onMounted(() => {
    initChart();
    chartRef.value && ro.observe(chartRef.value);
});
onBeforeUnmount(() => {
    ro.disconnect();
    chart?.dispose();
});

// 暴露给父组件
defineExpose({ resize });
</script>

<style scoped>
.pie-chart {
    width: 100%;
    height: 100%;
}
</style>
